#ifndef _UPO_SOLVER_H_
#define _UPO_SOLVER_H_

#include <stack>
#include <vector>
#include "parser.h"


using namespace std;

struct SystemState
{
	int indexToNodes;
	int coveredLines;
	int totalNodes;
	int targetNode;

	void InitState()
	{
		indexToNodes = 0;
		coveredLines = 0;
		totalNodes = 0;
	}

	void CopyState(SystemState state)
	{
		totalNodes = state.totalNodes;
		coveredLines = state.coveredLines;
		indexToNodes = state.indexToNodes;
		targetNode = state.targetNode;
	}

};

class UPO_solver
{
public:
	UPO_solver(InputData* _inputMatrix);
	~UPO_solver();

	void Solve();
	void WriteSolutionMask();
	int GetActiveNodesNumber(bool* mask, int iNodes);
	void PrintStats();
	int GetRank(){return m_iMyRank;}
	void SetRank(int iRank) {m_iMyRank = iRank;}
	void SendToken();
	void EmtyStack();
	void SplitWork();
	void AskForWork();
	void EmptyQueue();
	void SendWork(int);
	//void ReceiveBestMask();
	//void SendBestMask();
	
	void DivideJob();
	

private:


	struct Solution
	{
		int activeNodes;
		bool* solutionMask;

		void CopyMask(bool* mask, int totalNodes)
		{
			for(int i = 0; i < totalNodes; i++)
			{
				solutionMask[i] = mask[i];
			}
		}
	};
	
	/* stats for debug */
	typedef struct _Stats 
	{
		int expandNodes;
		int workRequestSend;
		int workRequestRefuse;
		int workRequestReceive;
		int workReceive;
		int workSend;
		int msgToken;
		int maxStackSize;
		//int newMaskTook;
		//int newMaskRefuse;
	} ProcessStats;


	void CheckMessageQueue();
	void ProcessStack();
	
	void SerializeStack(std::stack<SystemState> stack);
	std::stack<SystemState> DeserializeStack(void);
	
	char* SerializeBestMask();
	bool* DeserializeBestMask(char*);


	void ProcessStackItem(SystemState actualState);
	void MakeParallelReduction();
	
	ProcessStats stats;

	InputData* inputMatrix;
	int LinesNumber;
	std::stack<SystemState> MainStack;
	Solution currentBestSolution;
	bool* CurrentNodesMask;

	int m_iMyRank;
	bool m_bSolvingFinished;
	bool m_bTokenSend;
	bool workReqSend;
	int	 workReqTarget;
	char *msgBuffer;
};


#endif
